﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Model;
using System.Drawing.Imaging;

namespace ExecucaoGravacao
{
    public partial class ExecucaoGravacao : Form
    {
        public ExecucaoGravacao()
        {
            InitializeComponent();
        }

        int width_orig = SystemInformation.VirtualScreen.Width;
        int height_orig = SystemInformation.VirtualScreen.Height;
        System.Threading.Thread thread = null;
        public List<string> files = new List<string>();
        bool multilple = false;
        int count_eventos = 0;

        List<Evento> eventos = new List<Evento>();
        List<Evento> eventos_menu = new List<Evento>();
        DateTime dtInicio = DateTime.Now;

        // Get a handle to an application window.
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        // Activate an application window.
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

        [DllImport("user32.dll")]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

        [DllImport("user32.dll")]
        private static extern short VkKeyScan(char ch);


        const int MOUSEEVENTF_MOVE = 0x00000001;
        const int MOUSEEVENTF_LEFTDOWN = 0x00000002;
        const int MOUSEEVENTF_LEFTUP = 0x00000004;
        const int MOUSEEVENTF_RIGHTDOWN = 0x00000008;
        const int MOUSEEVENTF_RIGHTUP = 0x00000010;
        const int MOUSEEVENTF_MIDDLEDOWN = 0x00000020;
        const int MOUSEEVENTF_MIDDLEUP = 0x00000040;
        const int MOUSEEVENTF_WHEEL = 0x00000800;
        const int MOUSEEVENTF_ABSOLUTE = 0x00008000;

        public int tempHeight;
        public int tempWidth;

        private void btnProcurar_Click(object sender, EventArgs e)
        {
            openFileDialog1.Multiselect = true;
            openFileDialog1.ShowDialog(this);

            if(openFileDialog1.FileNames.Length > 1)
            {
                SelecionaOrdem ordem = new SelecionaOrdem();
                ordem.files = openFileDialog1.FileNames.ToList<string>();
                ordem.ShowDialog(this);

                multilple = true;
            }
            else
            {

                multilple = false;
                //lê o xml
                DataSet ds = new DataSet();
                ds.ReadXml(openFileDialog1.FileName, XmlReadMode.ReadSchema);

                foreach(DataRow dr in ds.Tables[0].Rows)
                {
                    Evento evento = EfetuaLeituraEvento(dr);
                }

                //numero de casos de execução
                label4.Text = "Número de Passos: " + ds.Tables[0].Rows.Count;
            }
        }

        private void btnExecutar_Click(object sender, EventArgs e)
        {
            //this.WindowState = FormWindowState.Minimized;
            //Screen Srn = Screen.PrimaryScreen;
            //tempHeight = Srn.Bounds.Height;
            //tempWidth = Srn.Bounds.Width;

            //new Model.Resolution.CResolution(1024, 768);





            if(chkLogin.Checked)
            {
                //faz o login no Sinacor com os dados passados

                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo.FileName = @"C:\DSEPROJ\Compilados\Sinacor\UI\Application\Sinacor.exe";
                proc.Start();
                proc.WaitForInputIdle();
                System.Threading.Thread.Sleep(15000);


                foreach(Char c in txtUsuario.Text.ToUpper())
                {
                    short num = VkKeyScan(c);
                    keybd_event((byte)num, 0x45, 0, 0);
                    keybd_event((byte)num, 0x45, 2, 0);
                    System.Threading.Thread.Sleep(200);
                }


                keybd_event((byte)Keys.Tab, 0x45, 0, 0);
                keybd_event((byte)Keys.Tab, 0x45, 2, 0);
                System.Threading.Thread.Sleep(200);

                foreach(Char c in txtSenha.Text.ToUpper())
                {
                    short num = VkKeyScan(c);
                    keybd_event((byte)num, 0x45, 0, 0);
                    keybd_event((byte)num, 0x45, 2, 0);
                    System.Threading.Thread.Sleep(200);
                }

                keybd_event((byte)Keys.Enter, 0x45, 0, 0);
                keybd_event((byte)Keys.Enter, 0x45, 2, 0);
                System.Threading.Thread.Sleep(200);

                

            }

            


            System.Threading.Thread thread_menu = new System.Threading.Thread(new System.Threading.ThreadStart(ExecutaPassosMenu));

            if(eventos_menu != null && eventos_menu.Count > 0)
            {
                System.Threading.Thread.Sleep(10000);
                thread_menu.Start();
            }

            while(thread_menu.IsAlive)
                System.Threading.Thread.Sleep(1000);


            if(multilple)
            {
                thread = new System.Threading.Thread(new System.Threading.ThreadStart(ExecutaPassosMultiplos));
                thread.ApartmentState = System.Threading.ApartmentState.STA;
                thread.Start();
            }
            else
            {
                thread = new System.Threading.Thread(new System.Threading.ThreadStart(ExecutaPassos));
                thread.ApartmentState = System.Threading.ApartmentState.STA;
                thread.Start();
            }

            while(thread.IsAlive)
                System.Threading.Thread.Sleep(1000);

            //new Model.Resolution.CResolution(tempWidth, tempHeight);
            //this.WindowState = FormWindowState.Normal;
        }

        private void ExecutaPassosMenu()
        {
            //regra de tres para saber qual o tamanho da tela

            int width = SystemInformation.VirtualScreen.Width;
            int height = SystemInformation.VirtualScreen.Height;


            double mult_width = Convert.ToDouble(width) / Convert.ToDouble(width_orig);
            double mult_height = Convert.ToDouble(height) / Convert.ToDouble(height_orig);



            count_eventos = eventos_menu.Count;

            int count_evento = 0;


            notifyIcon1.ShowBalloonTip(1000, "PREPARANDO EVENTO", "Aguarde início da execução", ToolTipIcon.Info);

            foreach(Evento evento in eventos_menu)
            {
                if(count_evento == 0)
                    evento.Diferenca = 10000;

                System.Threading.Thread.Sleep(Convert.ToInt32(evento.Diferenca));

                #region Mouse
                if(evento.TipoEvento == TipoEvento.Mouse)
                {

                    double meio_orig_width = evento.PointX - (Convert.ToDouble(width_orig) / 2);
                    double novo_ponto_width = (Convert.ToDouble(width) / 2) + meio_orig_width;

                    double meio_orig_height = evento.PointY - (Convert.ToDouble(height_orig) / 2);
                    double novo_ponto_height = (Convert.ToDouble(height) / 2) + meio_orig_height;



                    Cursor.Position = new Point(Convert.ToInt32(novo_ponto_width), Convert.ToInt32(novo_ponto_height));



                    switch(evento.TipoBotao)
                    {
                        case TipoBotao.Direito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.Esquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploEsquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploDireito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        default:
                            break;
                    }
                }
                #endregion

                #region Keyboard

                if(evento.TipoEvento == TipoEvento.Keyboard)
                {
                    Char c = (Char)evento.Tecla;
                    short num = VkKeyScan(c);

                    
                    if(evento.TipoKey == TipoKey.Down)
                        keybd_event((byte)num, 0x45, 0, 0);
                    else
                        keybd_event((byte)num, 0x45, 2, 0);




                    //byte[] teste = BitConverter.GetBytes(evento.Tecla);
                }

                #endregion

                count_evento++;

                //executando evento
                notifyIcon1.ShowBalloonTip(1000, "EXECUTANDO EVENTO MENU", "Executando evento " + count_evento + " de " + count_eventos, ToolTipIcon.Info);
            }

        }


        private void ExecutaPassosMultiplos()
        {
            //regra de tres para saber qual o tamanho da tela

            int width = SystemInformation.VirtualScreen.Width;
            int height = SystemInformation.VirtualScreen.Height;


            double mult_width = Convert.ToDouble(width) / Convert.ToDouble(width_orig);
            double mult_height = Convert.ToDouble(height) / Convert.ToDouble(height_orig);



            count_eventos = eventos.Count;

            //int count_evento = 0;


            foreach(string filename in files)
            {

                DataSet ds = new DataSet();
                ds.ReadXml(filename, XmlReadMode.ReadSchema);


                eventos = new List<Evento>();
                foreach(DataRow dr in ds.Tables[0].Rows)
                {
                    Evento evento = EfetuaLeituraEvento(dr);
                }

                ExecutaPassos();

                System.Threading.Thread.Sleep(3000);

                //TirarPrintScreen();


            }



            
        }

        private void TirarPrintScreen()
        {
            keybd_event((byte)Keys.PrintScreen, 0x45, 0, 0);
            keybd_event((byte)Keys.PrintScreen, 0x45, 2, 0);

            Image sBit = Clipboard.GetImage();
            sBit.Save(string.Format("c:\\print_screen_{0}.jpg",DateTime.Now.ToString("ddMMyyyyHH24mmss")), ImageFormat.Jpeg);
        }

        private Evento EfetuaLeituraEvento(DataRow dr)
        {
            Evento evento = new Evento();
            evento.Diferenca = Convert.ToDouble(dr["Diferenca"]);
            if(dr["PointX"] != null && dr["PointX"] != DBNull.Value)
                evento.PointX = Convert.ToInt32(dr["PointX"]);

            if(dr["PointY"] != null && dr["PointY"] != DBNull.Value)
                evento.PointY = Convert.ToInt32(dr["PointY"]);

            if(dr["Tecla"] != null && dr["Tecla"] != DBNull.Value)
                evento.Tecla = Convert.ToInt32(dr["Tecla"]);

            evento.TipoBotao = TraduzBotao(dr["TipoBotao"]);
            evento.TipoEvento = TraduzEvento(dr["TipoEvento"]);
            evento.TipoKey = TraduzTipoKey(dr["TipoKey"]);

            eventos.Add(evento);


            width_orig = Convert.ToInt32(dr["Width"]);
            height_orig = Convert.ToInt32(dr["Height"]);

            return evento;
        }

        private TipoKey TraduzTipoKey(object p)
        {
            if(p.ToString() == "Down")
                return TipoKey.Down;
            else
                return TipoKey.Up;
        }

        private void ExecutaPassos()
        {
            //regra de tres para saber qual o tamanho da tela

            int width = SystemInformation.VirtualScreen.Width;
            int height = SystemInformation.VirtualScreen.Height;


            double mult_width = Convert.ToDouble(width) / Convert.ToDouble(width_orig);
            double mult_height = Convert.ToDouble(height) / Convert.ToDouble(height_orig);



            count_eventos = eventos.Count;

            int count_evento = 0;

            notifyIcon1.ShowBalloonTip(1000, "PREPARANDO EVENTO", "Aguarde início da execução", ToolTipIcon.Info);

            foreach(Evento evento in eventos)
            {
                if(count_evento == 0)
                    evento.Diferenca = 5000;

                System.Threading.Thread.Sleep(Convert.ToInt32(evento.Diferenca));

                #region Mouse
                if(evento.TipoEvento == TipoEvento.Mouse)
                {

                    double meio_orig_width = evento.PointX - (Convert.ToDouble(width_orig) / 2);
                    double novo_ponto_width = (Convert.ToDouble(width) / 2) + meio_orig_width;

                    double meio_orig_height = evento.PointY - (Convert.ToDouble(height_orig) / 2);
                    double novo_ponto_height = (Convert.ToDouble(height) / 2) + meio_orig_height;



                    Cursor.Position = new Point(Convert.ToInt32(novo_ponto_width), Convert.ToInt32(novo_ponto_height));



                    switch(evento.TipoBotao)
                    {
                        case TipoBotao.Direito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.Esquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploEsquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploDireito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        default:
                            break;
                    }
                }
                #endregion

                #region Keyboard

                if(evento.TipoEvento == TipoEvento.Keyboard)
                {
                    Char c = (Char)evento.Tecla;
                    c = c.ToString().ToUpper().ToCharArray()[0];
                    if((evento.Tecla >= 112 && evento.Tecla <= 123 )
                        || (evento.Tecla >= 96 && evento.Tecla <= 105)
                        || (evento.Tecla >= 49 && evento.Tecla <= 57)
                        || (evento.Tecla == 46) || (evento.Tecla == 36)
                        || (evento.Tecla == 8)  || (evento.Tecla == 33)
                        || (evento.Tecla == 34) || (evento.Tecla == 46)
                        || (evento.Tecla == 35) || (evento.Tecla == 37)
                        || (evento.Tecla == 38) || (evento.Tecla == 39)
                        || (evento.Tecla == 40) || (evento.Tecla == 160)
                        || (evento.Tecla == 162) || (evento.Tecla == 164) 

                        )
                    {
                        if(evento.TipoKey == TipoKey.Down)
                            keybd_event((byte)evento.Tecla, 0x45, 0, 0);
                        else
                            keybd_event((byte)evento.Tecla, 0x45, 2, 0);
                    }
                    else
                    {
                        short num = VkKeyScan(c);
                        if(evento.TipoKey == TipoKey.Down)
                            keybd_event((byte)num, 0x45, 0, 0);
                        else
                            keybd_event((byte)num, 0x45, 2, 0);
                    }




                    //byte[] teste = BitConverter.GetBytes(evento.Tecla);
                }

                #endregion

                if (evento.TipoEvento == TipoEvento.PrintScreen)
                {
                    TirarPrintScreen();
                }

                count_evento++;

                //executando evento
                notifyIcon1.ShowBalloonTip(1000, "EXECUTANDO EVENTO", "Executando evento " + count_evento + " de " + count_eventos, ToolTipIcon.Info);
            }

            notifyIcon1.ShowBalloonTip(1000, "FINALIZANDO EVENTOS", "Eventos finalizados com sucesso!", ToolTipIcon.Info);
        }

        private TipoEvento TraduzEvento(object p)
        {
            if(p.ToString() == "Mouse")
                return TipoEvento.Mouse;
            else if (p.ToString() == "Keyboard")
                return TipoEvento.Keyboard;
            else
                return TipoEvento.PrintScreen;
        }

        private TipoBotao TraduzBotao(object p)
        {
            if(p.ToString() == "Esquerdo")
                return TipoBotao.Esquerdo;
            else if(p.ToString() == "Direito")
                return TipoBotao.Direito;
            else if(p.ToString() == "DuploEsquerdo")
                return TipoBotao.DuploEsquerdo;
            else if(p.ToString() == "DuploDireito")
                return TipoBotao.DuploDireito;
            else
                return TipoBotao.Direito;

        }


        private void toolStripMenuItem1_Click_1(object sender, EventArgs e)
        {
            //parar execução
            if(thread != null)
                thread.Abort();

            thread = null;

            notifyIcon1.ShowBalloonTip(1000, "EXECUÇÂO ABORTADA", "Execução abortada pelo usuário!", ToolTipIcon.Info);
        }

        private void chkLogin_Click(object sender, EventArgs e)
        {
            label5.Visible = chkLogin.Checked;
            label6.Visible = chkLogin.Checked;
            txtUsuario.Visible = chkLogin.Checked;
            txtSenha.Visible = chkLogin.Checked;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog(this);

            //lê o xml

            DataSet ds = new DataSet();
            ds.ReadXml(openFileDialog1.FileName, XmlReadMode.ReadSchema);


            foreach(DataRow dr in ds.Tables[0].Rows)
            {
                Evento evento = new Evento();
                evento.Diferenca = Convert.ToDouble(dr["Diferenca"]);
                if(dr["PointX"] != null && dr["PointX"] != DBNull.Value)
                    evento.PointX = Convert.ToInt32(dr["PointX"]);

                if(dr["PointY"] != null && dr["PointY"] != DBNull.Value)
                    evento.PointY = Convert.ToInt32(dr["PointY"]);

                if(dr["Tecla"] != null && dr["Tecla"] != DBNull.Value)
                    evento.Tecla = Convert.ToInt32(dr["Tecla"]);

                evento.TipoBotao = TraduzBotao(dr["TipoBotao"]);
                evento.TipoEvento = TraduzEvento(dr["TipoEvento"]);

                eventos_menu.Add(evento);


                width_orig = Convert.ToInt32(dr["Width"]);
                height_orig = Convert.ToInt32(dr["Height"]);
            }

            //numero de casos de execução
            label7.Text = "Número de Passos Menu: " + ds.Tables[0].Rows.Count;
        }
    }
}
